/*
 *  AudioPlayer.cpp
 *  SoundController0002
 *
 *  Created by jiro on 10/07/03.
 *  Copyright 2010 jiro music. All rights reserved.
 *
 */

#include "AudioPlayer.h"
#include "Constants.h"
#include "Utility.h"
#include <CoreAudio/CoreAudio.h>
#include <CoreServices/CoreServices.h>
#include <vector>
#include <iostream>

namespace sc
{
	AudioPlayer::AudioPlayer()
		: AudioUnitPlayer( AudioPlayer::RenderCallback )
	{}

	void AudioPlayer::LoadAudioData( const std::vector< std::vector< float >* >& audioDataByChannel )
	{
		this->audioDataByChannel = audioDataByChannel;
		playingIndexMax = GetIndexMax();
	}

	void AudioPlayer::Play( double time )
	{
		if ( audioDataByChannel.size() == 0 )
		{
			return;
		}

		playingIndex = time * Sampling_Rate_As_Int;
		AudioUnitPlayer::Play( time );
	}

	bool AudioPlayer::IsPlaying() const 
	{
		if ( playingIndex >= playingIndexMax )
		{
			return false;
		}
		return true;
	}

	void AudioPlayer::Skip( double time )
	{
		playingIndex += time * Sampling_Rate_As_Int;
	}

	void AudioPlayer::Pause()
	{
		AudioOutputUnitStop( audioUnit );
		AudioUnitPlayer::Pause();
	}

	void AudioPlayer::Stop()
	{
		playingIndex = playingIndexMax;
		AudioUnitPlayer::Stop();
	}

	int AudioPlayer::GetIndexMax() const
	{
		int max = 0;
		size_t count = audioDataByChannel.size();
		for ( int i = 0; i < count; i++ )
		{
			if ( audioDataByChannel[ i ]->size() > max )
			{
				max = audioDataByChannel[ i ]->size();
			}
		}
		return max;
	}

	OSStatus AudioPlayer::RenderCallback( 
		void* inRefCon,
		AudioUnitRenderActionFlags* ioActionFlag,
		const AudioTimeStamp* inTimeStamp,
		UInt32 inBusNumber,
		UInt32 inNumberFrames,
		AudioBufferList* ioData )
	{
		AudioPlayer* player = (AudioPlayer*) inRefCon;

		//	---- 前提をチェック
		if ( player->playingIndex >= player->playingIndexMax ||
			 player->playingIndex + inNumberFrames >= player->audioDataByChannel[ 0 ]->size() )
		{
			player->Stop();
			return noErr;
		}
		//	----

		int index = player->playingIndex;
		player->playingIndex += inNumberFrames;

		int channelCount = ioData->mNumberBuffers;
		std::vector< float* > dataPtrs( channelCount );
		for ( int channelIndex = 0; channelIndex < channelCount; channelIndex++ )
		{
			dataPtrs[ channelIndex ] = static_cast< float* >( ioData->mBuffers[ channelIndex ].mData );
		}

		for ( int i = 0; i < inNumberFrames; i++ )
		{
			for ( int channelIndex = 0; channelIndex < channelCount; channelIndex++ )
			{
				*( dataPtrs[ channelIndex ] ) = player->audioDataByChannel[ channelIndex ]->at( index );
				( dataPtrs[ channelIndex ] )++;
			}
			index++;
		}

		return noErr;

	}

}
